home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / VideoToolbox 96.06.15 / VideoToolboxSources / CopyWindows.c < prev    next >
Text File  |  1995-07-26  |  9KB  |  218 lines

  1. /*
  2. CopyWindows.c
  3.  
  4. CopyWindows(srcWindow,dstWindow,srcRectPtr,dstRectPtr,srcMode,maskRgn);
  5.  
  6. CopyWindows() provides a high-level interface to CopyBits and CopyBitsQuickly,
  7. accepting windows (WindowPtr, CWindowPtr, or GWorldPtr) instead of pixmaps or
  8. bitmaps.
  9.  
  10. You select CopyBitsQuickly by using a srcMode that has the "copyLiterally" bit
  11. set, i.e. either srcCopyLiterally, addOverLiterally, addOverParallelLiterally,
  12. or mulOverLiterally.
  13.  
  14. For your convenience, CopyWindows normally sets up the foreground and background
  15. colors to prevent undesired colorizing. If you want to colorize then add
  16. "copyColorize" to the srcMode argument.
  17.  
  18. CopyBits() is an extremely useful component of QuickDraw, but it's tricky to
  19. use, especially if you just want a faithful copy. Its user-interface was frozen
  20. a long time ago, when off-screen images were referred to by their BitMap
  21. pointers. Apple generalized its underlying code to accept PixMap pointers as
  22. well, but the reality is that nowadays the object that we work with is a window,
  23. either on-screen, or off-screen (i.e. a GWorld). CopyWindows accepts two
  24. windows, source and destination, figures out where the associated Pix/BitMaps
  25. are, and calls CopyBits or CopyBitsQuickly, after making all the appropriate
  26. incantations to get the desired results.
  27.  
  28. The allowed values for srcMode are documented by Apple along with CopyBits in the
  29. New Inside Mac: "Imaging with QuickDraw". The additional modes implemented by
  30. CopyBitsQuickly are documented in CopyBitsQuickly.c. CopyBits and
  31. CopyBitsQuickly define srcMode as a short. CopyWindows defines srcMode as a
  32. long, using two bits in the upper word as flags for copyLiterally and
  33. copyColorize. Here's a summary of the modes that I use most:
  34.  
  35. srcCopy
  36.  
  37. This mode is implemented by CopyBits. If the source and destination have the
  38. same depth (i.e. pixelSize) and exactly the same color table then you'll get
  39. faithful copying of the actual numbers stored in each pixel. (I'm assuming that
  40. the destination window has the same color table as its device, which will be
  41. true if you created the window using GDOpenWindow or NewGWorld.) If the source
  42. and destination have different color tables, e.g. because the pixel sizes
  43. differ, then CopyBits will translate via the color tables. CopyBits is perhaps
  44. Apple's prize piece of code and runs very fast, taking advantage of special
  45. instructions of particular processors (e.g. to do 64 bit moves on 68040 and
  46. PowerPC) and can do wonderful things, like stretch and shrink and mask by a
  47. region. Apple defines many other srcMode values but I never use them with
  48. CopyBits because they all result in color translations that I don't want.
  49.  
  50. srcCopyLiterally,addOverLiterally,addOverParallelLiterally,mulOverLiterally
  51.  
  52. These modes are implemented by CopyBitsQuickly, which never does color
  53. translation. addOverLiterally adds the pixel values, ignoring overflow.
  54. addOverParallelLiterally does the same, but does the addition for 32-bits at a
  55. time, adding several pixels at once, so that if overflow occurs it will overflow
  56. into an adjoing pixel. mulOverLiterally multiplies the (unsigned) pixels,
  57. divides the product by 128, and stores the result in the destination.
  58. CopyBitsQuickly has many restrictions. The source and destination must have the
  59. same rect size and the same pixel size. addOverLiterally and mulOverLiterally
  60. insist on 8-bit pixels. All the modes resolve only bytes, not bits, so a few
  61. bits at the left and right of your image may not be copied if that would require
  62. writing to a byte not all of whose bits are in the destination.
  63.  
  64. NOTES:
  65.  
  66. 0. Read "VideoToolbox:Notes:CopyBits slavishly".
  67.  
  68. 1. CopyBits has a rarely used feature called "colorizing" whereby if the
  69. foreground and background colors of the current port are not black and white
  70. then each source pixel's color is translated by linear interpolation between the
  71. foreground and background color. Programmers often forget about this, and are
  72. surprised by the undesired colorizing. To make life easier I've defined an extra
  73. bit in srcMode. If the "copyColorize" flag is false (nearly always the case)
  74. then CopyWindows will make sure no colorizing occurs by setting the fore and
  75. back colors to black and white. (The colors are restored before returning.)
  76.  
  77. 2. Apple's CopyBits uses the color table and palette of the source pixmap as
  78. you'd expect, but ignores the color table and palette of the destination pixmap,
  79. and instead uses the color table of the current device. This is annoying, and
  80. hard to remember. Apple did it this way because CopyBits uses the inverse color
  81. table, which takes a long time to compute, and they decided that it would be too
  82. time and memory intensive to maintain an inverse table for each window, so
  83. instead they maintain them only for devices. The operating system creates
  84. inverse color tables for all graphic devices. Thus it is important to remember
  85. to set the device before calling CopyBits. To save you the trouble, CopyWindows
  86. sets the device to be whatever device is associated with the destination window.
  87. The device is found by GetWindowDevice(), which, for an on-screen window,
  88. returns the screen device with largest intersection with the window's content,
  89. and for an off-screen window (i.e. GWorld), returns the GWorld's device. When
  90. you create your GWorld you should supply the color table of your device, 
  91. (*(*device)->gdPMap)->pmTable, if you'll later be copying from the GWorld
  92. to the device.
  93.  
  94. 3. CopyWindowsQuickly calls ShieldCursor(), to make up for the fact that
  95. CopyBitsQuickly doesn't. QuickDraw automatically calls ShieldCursor for all
  96. screen-drawing operations, but CopyBitsQuickly bypasses QuickDraw. The obvious
  97. cosmetic benefit of calling ShieldCursor is that it prevents the cursor from
  98. appearing within screen areas that are being read or written. A further, subtle,
  99. benefit of calling ShieldCursor is compatibility with the one or two video
  100. devices, e.g. Radius PowerView, that depend on notification from QuickDraw that
  101. they've been written to. According to the programmer who wrote the PowerView
  102. driver, it's enough to call ShieldCursor(), specifying the global rect that was
  103. modified. That's hard to do within CopyBitsQuickly because the PixMap doesn't
  104. have any global coordinates; it merely has local coordinates and the address of
  105. video memory. (One would have to use the video address to figure out the device,
  106. and get the global coordinates from the device.) But it's easy to call
  107. ShieldCursor from within CopyWindowsQuickly, since it has access to the windows,
  108. which include the necessary global coordinates.
  109.  
  110. HISTORY:
  111. 10/3/94 dgp wrote it.
  112. 11/5/94 dgp added the new flags copyLiterally and copyColorize.
  113. */
  114. #include "VideoToolbox.h"
  115. static int CopyWindowsQuickly(CWindowPtr srcWindow,CWindowPtr dstWindow
  116.     ,Rect *srcRectPtr,Rect *dstRectPtr,long srcMode,RgnHandle maskRgn);
  117.  
  118. int CopyWindows(CWindowPtr srcWindow,CWindowPtr dstWindow
  119.     ,Rect *srcRectPtr,Rect *dstRectPtr,long srcMode,RgnHandle maskRgn)
  120. {
  121.     GWorldPtr oldPort;
  122.     GDHandle oldDevice,device;
  123.     int error;
  124.     static const RGBColor blackRGB={0,0,0},whiteRGB={0xFFFF,0xFFFF,0xFFFF};
  125.     RGBColor foreRGB,backRGB;
  126.     ColorSpec foreColor,backColor;
  127.     BitMap *srcBits,*dstBits;
  128.     static Boolean qd8,qd32,firstTime=1;
  129.     Boolean colorize;
  130.     
  131.     if(srcMode & copyLiterally)
  132.         return CopyWindowsQuickly(srcWindow,dstWindow,srcRectPtr,dstRectPtr,srcMode,maskRgn);
  133.     colorize=(srcMode©Colorize)!=0;
  134.     srcMode&=0xffff;    // no more need for upper bits.
  135.     if(firstTime){
  136.         long qd;
  137.         Gestalt(gestaltQuickdrawVersion,&qd);
  138.         qd8 = qd>=gestalt8BitQD;
  139.         qd32 = qd>=gestalt32BitQD;
  140.         firstTime=0;
  141.     }
  142.     device=GetWindowDevice((WindowPtr)dstWindow);
  143.     if(qd32){
  144.         GetGWorld(&oldPort,&oldDevice);
  145.         SetGWorld((GWorldPtr)dstWindow,device);
  146.     }else{
  147.         GetPort((WindowPtr *)&oldPort);
  148.         SetPort((WindowPtr)dstWindow);
  149.         if(qd8){
  150.             oldDevice=GetGDevice();
  151.             SetGDevice(device);
  152.         }
  153.     }
  154.     if(!colorize && qd8){
  155.         GetForeColor(&foreRGB);
  156.         GetBackColor(&backRGB);
  157.         if(qd32){
  158.             SaveFore(&foreColor);
  159.             SaveBack(&backColor);
  160.         }
  161.         RGBForeColor(&blackRGB);  /* so CopyBits won't colorize  */
  162.         RGBBackColor(&whiteRGB);  /* so CopyBits won't colorize  */
  163.     }
  164.     srcBits=GetBitMapPtr(srcWindow);
  165.     dstBits=GetBitMapPtr(dstWindow);
  166.     if(srcBits==NULL || dstBits==NULL)return -1;
  167.     CopyBits(srcBits,dstBits,srcRectPtr,dstRectPtr,srcMode,maskRgn);
  168.     error=QDError();
  169.     if(!colorize && qd8){
  170.         RGBForeColor(&foreRGB);
  171.         RGBBackColor(&backRGB);
  172.         if(qd32){
  173.             RestoreFore(&foreColor);
  174.             RestoreBack(&backColor);
  175.         }
  176.     }
  177.     if(qd32){
  178.         SetGWorld(oldPort,oldDevice);
  179.     }else{
  180.         SetPort((WindowPtr)oldPort);
  181.         if(qd8)SetGDevice(oldDevice);
  182.     }
  183.     return error;
  184. }
  185.  
  186. static int CopyWindowsQuickly(CWindowPtr srcWindow,CWindowPtr dstWindow
  187.     ,Rect *srcRectPtr,Rect *dstRectPtr,long srcMode,RgnHandle maskRgn)
  188. {
  189.     int error,i,shields=0;
  190.     BitMap *srcBits,*dstBits;
  191.     Point pt;
  192.     WindowPtr oldPort;
  193.     
  194.     GetPort(&oldPort);
  195.     if(!IsGWorldPtr(srcWindow)){
  196.         SetPort((WindowPtr)srcWindow);
  197.         pt.h=pt.v=0;
  198.         LocalToGlobal(&pt);
  199.         ShieldCursor(srcRectPtr,pt);
  200.         shields++;
  201.     }
  202.     if(!IsGWorldPtr(dstWindow)){
  203.         SetPort((WindowPtr)dstWindow);
  204.         pt.h=pt.v=0;
  205.         LocalToGlobal(&pt);
  206.         ShieldCursor(dstRectPtr,pt);
  207.         shields++;
  208.     }
  209.     SetPort(oldPort);
  210.     srcBits=GetBitMapPtr(srcWindow);
  211.     dstBits=GetBitMapPtr(dstWindow);
  212.     if(srcBits==NULL || dstBits==NULL)return 4;
  213.     error=CopyBitsQuickly(srcBits,dstBits,srcRectPtr,dstRectPtr,srcMode,maskRgn);
  214.     for(i=0;i<shields;i++)ShowCursor();
  215.     return error;
  216. }
  217.  
  218.